package lib.bone.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.lang.Validator;
import lib.bone.common.constant.ResponseCodeConst;
import lib.bone.common.core.domain.PageResultDTO;
import lib.bone.common.core.domain.ResponseDTO;
import lib.bone.common.exception.BusinessException;
import lib.bone.system.dao.SysMenuDAO;
import lib.bone.system.dao.SysRoleDAO;
import lib.bone.system.dao.SysUserDAO;
import lib.bone.system.domain.dto.role.RoleAddDTO;
import lib.bone.system.domain.dto.role.RoleUpdateDTO;
import lib.bone.system.domain.entity.SysMenu;
import lib.bone.system.domain.entity.SysRole;
import lib.bone.system.domain.entity.SysUser;
import lib.bone.system.service.SysRoleService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.util.*;

/**
 * @author kindear
 * @date
 * 角色相关服务接口实现
 */
@Slf4j
@Service
public class SysRoleServiceImpl implements SysRoleService {

    @Autowired
    SysUserDAO sysUserDAO;

    @Autowired
    SysRoleDAO sysRoleDAO;


    @Autowired
    SysMenuDAO sysMenuDAO;


    @Autowired
    SysRoleMenuServiceImpl sysRoleMenuService;

    @Override
    public SysRole saveOne(SysRole sysRole) {

        if (Validator.isNotEmpty(sysRole.getId())){
            throw new BusinessException(ResponseCodeConst.ERROR_PARAM);
        }
        return sysRoleDAO.save(sysRole);
    }

    @Override
    public SysRole updateOne(SysRole sysRole) {
        if (Validator.isEmpty(sysRole.getId())){
            throw new BusinessException(ResponseCodeConst.ERROR_PARAM);
        }
        return sysRoleDAO.save(sysRole);
    }

    @Override
    public PageResultDTO<SysRole> getAll(Pageable pageable, Example<SysRole> example) {
        /**
         * 根据是否为空进行判断
         */
        Page<SysRole> sysRolePage;
        if(Validator.isEmpty(example)){
            sysRolePage = sysRoleDAO.findAll(pageable);
        }
        else {
            sysRolePage = sysRoleDAO.findAll(example,pageable);
        }
        /**
         * 获取分页主体内容
         */
        List<SysRole> sysRoleList = sysRolePage.getContent();
        PageResultDTO<SysRole> pageResultDTO = new PageResultDTO<>();

        pageResultDTO.setContent(sysRoleList);
        pageResultDTO.setSize(sysRolePage.getSize());
        pageResultDTO.setTotalPages(sysRolePage.getTotalPages());
        pageResultDTO.setNumber(sysRolePage.getNumber());
        pageResultDTO.setTotalElements(sysRolePage.getTotalElements());

        return pageResultDTO;
    }

    @Override
    public ResponseDTO<SysRole> saveOne(RoleAddDTO roleAddDTO) {
        SysRole sysRole = new SysRole();

        /**
         * 判断是否存在冲突数据
         */
        Optional<SysRole> sysRoleOp = sysRoleDAO.findByRoleNameOrRoleKey(roleAddDTO.getRoleName(), roleAddDTO.getRoleKey());
        if(sysRoleOp.isPresent()){
            return ResponseDTO.wrap(ResponseCodeConst.ERROR_PARAM,"角色名或角色标识已存在");
        }

        BeanUtil.copyProperties(roleAddDTO,sysRole, CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
        sysRole.setDataScope(1);
        /**
         * 查询对应的菜单
         */
        List<SysMenu> menus = sysMenuDAO.findByIdIn(roleAddDTO.getMenuIds());
        List<String> perms = new ArrayList<>();
        menus.forEach(ele->{
            if(Validator.isNotEmpty(ele.getPerms())){
                perms.add(ele.getPerms());
            }
        });

        sysRole.setPermission(perms);

        SysRole res =  sysRoleDAO.save(sysRole);
        /**
         * 将关联关系写入
         */
        sysRoleMenuService.batchAddRoleMenu(res.getId(),roleAddDTO.getMenuIds());
        return ResponseDTO.succData(res);
    }

    @Override
    @Transactional
    public ResponseDTO updateOne(RoleUpdateDTO roleUpdateDTO) {
        Optional<SysRole> sysRoleOp = sysRoleDAO.findById(roleUpdateDTO.getId());
        if(!sysRoleOp.isPresent()) return ResponseDTO.wrap(ResponseCodeConst.NOT_FOUND);
        SysRole sysRole = sysRoleOp.get();
        BeanUtil.copyProperties(roleUpdateDTO,sysRole,CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
        List<SysMenu> menus = sysMenuDAO.findByIdIn(roleUpdateDTO.getMenuIds());
        List<String> perms = new ArrayList<>();
        menus.forEach(ele->{
            if(Validator.isNotEmpty(ele.getPerms())){
                perms.add(ele.getPerms());
            }
        });
        sysRole.setPermission(perms);
        /**
         * 清理一下
         */
        sysRoleMenuService.deleteByRoleId(roleUpdateDTO.getId());
        SysRole res =  sysRoleDAO.save(sysRole);
        log.info(roleUpdateDTO.getMenuIds().toString());
        sysRoleMenuService.batchAddRoleMenu(roleUpdateDTO.getId(), roleUpdateDTO.getMenuIds());
        return ResponseDTO.succData(res);
    }

    @Override
    public ResponseDTO deleteById(Long roleId) {
        Optional<SysRole> sysRoleOp = getById(roleId);
        if(!sysRoleOp.isPresent()){
            return ResponseDTO.wrap(ResponseCodeConst.NOT_FOUND);
        }
        sysRoleDAO.deleteById(roleId);
        return ResponseDTO.succMsg("删除成功!");
    }

//    @Override
//    public List<String> getRolePerms(Long roleId) {
//        Optional<SysRole> sysRoleOp = sysRoleDAO.findById(roleId);
//        List<String> permsList = new ArrayList<>();
//        if (!sysRoleOp.isPresent()) {
//            return permsList;
//        }
//        SysRole sysRole = sysRoleOp.get();
//
//        return sysRole.getPermission();
//    }

    @Override
    @Transactional
    public Optional<SysRole> getById(Long roleId) {
        return sysRoleDAO.findById(roleId);
    }



    @Override
    public List<SysRole> getAll(){
        return sysRoleDAO.findAll();
    }

    /**
     * 修改角色状态
     */

    @Override
    public ResponseDTO<SysRole> changeRoleStatus(Long roleId,Integer status){
        Optional<SysRole> sysRoleOp = getById(roleId);
        if(!sysRoleOp.isPresent())
            return ResponseDTO.wrap(ResponseCodeConst.NOT_FOUND);
        SysRole sysRole = sysRoleOp.get();
        sysRole.setStatus(status);
        return ResponseDTO.succData(updateOne(sysRole));
    }


}
